﻿using System;
using System.Collections.Generic;

using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using FSViet.Survey.Helpers;
using System.Data.SqlClient;
using System.Data;
using System.Web.UI.HtmlControls;
using log4net;

namespace FSViet.Survey.Administration.Question
{
	public partial class FormView : ListPageBase
	{
		bool _canEdit = false;
		#region TotalQuestionOnPage

		int TotalQuestionOnPage
		{
			get
			{
				return Convert.ToInt32(Request.QueryString["TotalQuestionOnPage"]);
			}
		}
		#endregion

		#region TotalQuestion

		public int TotalQuestion
		{
			get
			{
				int result = 0;
				if (ViewState["TotalQuestion"] != null)
					result = (int)ViewState["TotalQuestion"];
				else
					result = -1;

				return result;
			}
			set
			{
				ViewState["TotalQuestion"] = value;
			}
		}
		#endregion

		ILog _logger = LogManager.GetLogger("RollingFile");
		protected void Page_Load(object sender, EventArgs e)
		{
			CheckCampaign();
				_campaignId = new Guid(Request.QueryString["CampaignId"]);
				LoadData(_campaignId);
		}

		Guid _campaignId = Guid.Empty;
		DataHelper _dataH = new DataHelper();
		SqlConnection _conn = null;
		DataTable _questions = null;
		void LoadData(Guid id)
		{
			_conn = _dataH.CreateConnection();
			try
			{
				_conn.Open();
				try
				{
					if (TotalQuestionOnPage < 1)
					{
						ShowAllQuestion(id, false);
					}
					else
					{
						msg.Text = "";
						NextButton.Visible = true;
						SubmitAfterReviewButton.Visible = false;
						#region //current version show only one question, and all question of group

						if (TotalQuestion < 0)
						{
							var questionsTemp = _dataH.Load(_conn, "SELECT * FROM Questions WHERE CampaignId=@CampaignId AND IsAnswerGroup='False'", 0, 100,
							_dataH.CreateParam("CampaignId", SqlDbType.Char, GlobalApplication.GetGuidS(id)));
							CalculateTotalQuestion(questionsTemp);
						}

						if (CurrentQuestionIndex <= TotalQuestion)
						{
							var questions = _dataH.Load(_conn, "SELECT * FROM Questions WHERE CampaignId=@CampaignId AND IsAnswerGroup='False' " + BuildCondiction() +" ORDER BY Created", 0, 1,
								_dataH.CreateParam("CampaignId", SqlDbType.Char, GlobalApplication.GetGuidS(id)));
							_questions = questions.Clone();

							DataRow dr = null;
							if (questions.Rows.Count > 0)
								dr = questions.Rows[0];
							//if (dr != null)
							//{
							if (dr["GroupId"] == DBNull.Value
								|| dr["GroupId"].ToString() == GlobalApplication.GetGuidS(Guid.Empty))
							{
								_questions = questions.Copy();
								//render single question
								SurveyFormPanel.Controls.Add(RenderQuestion(false, "Câu hỏi " + CurrentQuestionIndex+": ", dr));
							}
							else
							{
								//_questions = new DataTable();
								#region render group question

								//load group info
								var group = _dataH.Load(_conn, "SELECT * FROM Groups WHERE Id=@Id", 0, 100,
									_dataH.CreateParam("Id", SqlDbType.Char, dr["GroupId"]));
								var div = new HtmlGenericControl("div");
								div.InnerHtml = "<span class='prefix'>Câu hỏi " + CurrentQuestionIndex + ": </span>" + group.Rows[0]["Name"].ToString();
								if (_canEdit)
								{
									var item = new HtmlGenericControl("a");
									item.InnerText = " Edit group";
									item.Attributes.Add("href", "../Group/Details.aspx?Id=" + group.Rows[0]["Id"].ToString());
									div.Controls.Add(item);
								}
								//div.Controls.Add(RenderQuestionControlView(dr, "Câu hỏi " + CurrentQuestionIndex + ":"));
								if (_canEdit)
								{
									var item = new HtmlGenericControl("a");
									item.InnerText = " Edit group";
									item.Attributes.Add("href", "../Group/Details.aspx?Id=" + group.Rows[0]["Id"].ToString());
									div.Controls.Add(item);
								}
								
								//div.InnerHtml = "<span class='prefix'>Câu hỏi " + CurrentQuestionIndex + ": </span>" + group.Rows[0]["Name"].ToString();
								//add group info
								SurveyFormPanel.Controls.Add(div);
								var groupId = group.Rows[0]["Id"].ToString();
								//if (dr["AnswerGroupId"] == DBNull.Value
								//|| dr["AnswerGroupId"].ToString() == GlobalApplication.GetGuidS(Guid.Empty))
								//{
								//  //question in group
								//  SurveyFormPanel.Controls.Add(RenderQuestion(dr));
								//}
								//else
								//{
								var questionsInGroup = _dataH.Load(_conn, "SELECT * FROM Questions WHERE GroupId=@Id", 0, 100,
									_dataH.CreateParam("Id", SqlDbType.Char, dr["GroupId"]));

								DataRow questionInGroup;
								//totalQuestion = questions.Rows.Count; //update total question after filter question in group
								var totalQuestionsInGroup = questionsInGroup.Rows.Count;
								//for (int j = 0; j < totalQuestionsInGroup; j++)
								while (totalQuestionsInGroup > 0)
								{
									questionInGroup = questionsInGroup.Rows[0];
									if (questionInGroup["AnswerGroupId"] == DBNull.Value
										|| questionInGroup["AnswerGroupId"].ToString() == GlobalApplication.GetGuidS(Guid.Empty))
									{
										AddMappingQuestion(_questions, questionInGroup);
										//question not use answer group
										SurveyFormPanel.Controls.Add(RenderQuestion(false, "", questionInGroup["Name"].ToString() != group.Rows[0]["Name"].ToString(), questionInGroup));
										questionsInGroup.Rows.Remove(questionInGroup);
										totalQuestionsInGroup = questionsInGroup.Rows.Count;
									}
									else
									{
										//question use answer group
										var answerGroupId = questionInGroup["AnswerGroupId"].ToString();
										//filter all question use answer group
										var questionsUseAnswerGroup = GetQuestionGroupAnswerGroup(groupId, answerGroupId, questionsInGroup);
										totalQuestionsInGroup = questionsInGroup.Rows.Count; //update total question in group
										var answerGroup = _dataH.Load(_conn, "SELECT * FROM Questions WHERE Id=@Id", 0, 100,
											_dataH.CreateParam("Id", SqlDbType.Char, answerGroupId));
										//render questions use answer group
										SurveyFormPanel.Controls.Add(RenderQuestionAnswerGroup(false, "", group.Rows[0], answerGroup.Rows[0], questionsUseAnswerGroup, _questions));
									}
								}

								#endregion
							}
							//_questions = questions.Copy();

							CurrentQuestionLabel.Text = CurrentQuestionIndex + "/" + TotalQuestion;
						}
						else
						{
							SubmitAfterReviewButton.Visible = true;
							NextButton.Visible = false;
							//not found any question save answer and move to success page
							//SaveAnswer(Answers);
							ShowAllQuestion(id, true);
						}
						#endregion
					}
				}
				finally
				{
					_conn.Close();
				}
			}
			catch (Exception ex)
			{
				msg.Text = ex.Message;
#if DEBUG
				msg.Text = ex.ToString().Replace("\r\n", "<br/>");
#endif
			}
		}

		void ShowAllQuestion(Guid campaignId, bool isReview)
		{
			#region display all question

			var questions = _dataH.Load(_conn, "SELECT * FROM Questions WHERE CampaignId=@CampaignId AND IsAnswerGroup='False' ORDER BY Created", 0, 100,
				_dataH.CreateParam("CampaignId", SqlDbType.Char, GlobalApplication.GetGuidS(campaignId)));
			_questions = questions.Copy();
			DataRow dr;
			int totalQuestion = questions.Rows.Count;
			int i = 0;
			while (totalQuestion > -1)
			{
				dr = questions.Rows[0];
				if (dr["GroupId"] == DBNull.Value
					|| dr["GroupId"].ToString() == GlobalApplication.GetGuidS(Guid.Empty))
				{
					//render single question
					SurveyFormPanel.Controls.Add(RenderQuestion(isReview, "Câu hỏi " + (i + 1)+": ", dr));
					questions.Rows.RemoveAt(0);
				}
				else
				{
					#region render group question

					//load group info
					var group = _dataH.Load(_conn, "SELECT * FROM Groups WHERE Id=@Id", 0, 100,
						_dataH.CreateParam("Id", SqlDbType.Char, dr["GroupId"]));
					var div = new HtmlGenericControl("div");
					div.InnerHtml = "<span class='prefix'>Câu hỏi " + (i + 1) + ": </span>" + group.Rows[0]["Name"].ToString();
					//var div = new HtmlGenericControl("div");
					//dr["Name"] = group.Rows[0]["Name"];
					//div.Controls.Add(RenderQuestionControlView(dr, "Câu hỏi " + CurrentQuestionIndex + ":"));
					if (_canEdit)
					{
						var item = new HtmlGenericControl("a");
						item.InnerText = " Edit group";
						item.Attributes.Add("href", "../Group/Details.aspx?Id=" + group.Rows[0]["Id"].ToString());
						div.Controls.Add(item);
					}
					//add group info
					SurveyFormPanel.Controls.Add(div);
					var groupId = group.Rows[0]["Id"].ToString();
					//if (dr["AnswerGroupId"] == DBNull.Value
					//|| dr["AnswerGroupId"].ToString() == GlobalApplication.GetGuidS(Guid.Empty))
					//{
					//  //question in group
					//  SurveyFormPanel.Controls.Add(RenderQuestion(dr));
					//}
					//else
					//{
					var questionsInGroup = GetQuestionGroupAnswerGroup(groupId, questions);
					DataRow questionInGroup;
					totalQuestion = questions.Rows.Count; //update total question after filter question in group
					var totalQuestionsInGroup = questionsInGroup.Rows.Count;
					//for (int j = 0; j < totalQuestionsInGroup; j++)
					while(totalQuestionsInGroup>0)
					{
						questionInGroup = questionsInGroup.Rows[0];
						if (questionInGroup["AnswerGroupId"] == DBNull.Value
							|| questionInGroup["AnswerGroupId"].ToString() == GlobalApplication.GetGuidS(Guid.Empty))
						{
							//question not use answer group
							SurveyFormPanel.Controls.Add(RenderQuestion(isReview, "", questionInGroup["Name"].ToString() != group.Rows[0]["Name"].ToString(), questionInGroup));
							questionsInGroup.Rows.Remove(questionInGroup);
							totalQuestionsInGroup = questionsInGroup.Rows.Count;
						}
						else
						{
							//question use answer group
							var answerGroupId = questionInGroup["AnswerGroupId"].ToString();
							//filter all question use answer group
							var questionsUseAnswerGroup = GetQuestionGroupAnswerGroup(groupId, answerGroupId, questionsInGroup);
							totalQuestionsInGroup = questionsInGroup.Rows.Count; //update total question in group
							var answerGroup = _dataH.Load(_conn, "SELECT * FROM Questions WHERE Id=@Id", 0, 100,
								_dataH.CreateParam("Id", SqlDbType.Char, answerGroupId));
							//render questions use answer group
							SurveyFormPanel.Controls.Add(RenderQuestionAnswerGroup(isReview, "", group.Rows[0], answerGroup.Rows[0], questionsUseAnswerGroup));
						}
					}

					#endregion
				}

				totalQuestion -= 1;
				i += 1;
			}

			#endregion
		}

		/// <summary>
		/// Calculate total question of campaign
		/// </summary>
		/// <param name="questions">List all question of campaign</param>
		void CalculateTotalQuestion(DataTable questions)
		{
			//DataTable temp = questions.Copy();

			int counter = 0;
			DataRow dr;
			string emptyId = GlobalApplication.GetGuidS(Guid.Empty);
			while (questions.Rows.Count > 0)
			{
				dr = questions.Rows[0];
				if (dr["GroupId"] == DBNull.Value || dr["GroupId"].ToString() == emptyId)
				{
					questions.Rows.RemoveAt(0);
				}
				else
				{
					RemoveQuestionInGroup(questions, dr["GroupId"].ToString());
				}

				counter += 1;
			}

			TotalQuestion = counter;
		}

		/// <summary>
		/// Remove all question have same group
		/// </summary>
		/// <param name="questions">Source question list</param>
		/// <param name="groupId">Must be dif with empty value</param>
		void RemoveQuestionInGroup(DataTable questions, string groupId)
		{
			int total = questions.Rows.Count;
			DataRow dr;
			for (int i = 0; i < total; )
			{
				dr = questions.Rows[i];
				if (dr["GroupId"].ToString() == groupId)
				{
					questions.Rows.RemoveAt(i);
					total = questions.Rows.Count;
				}
				else
					i++;
			}
		}

		void AddMappingQuestion(DataTable target, DataRow dr)
		{
			var temp = target.NewRow();
			temp["Id"] = dr["Id"];
			temp["Name"] = dr["Name"];
			temp["GroupId"] = dr["GroupId"];
			temp["AnswerGroupId"] = dr["AnswerGroupId"];

			target.Rows.Add(temp);
		}

		string BuildCondiction()
		{
			string result = "";

			var answers = Answers;
			foreach (var item in answers)
			{
				if (result.IndexOf(item.QuestionId) > 1)
					continue;
				result += " AND Id!='" + item.QuestionId + "'";
			}

			return result;
		}

		/// <summary>
		/// Get question in group
		/// </summary>
		/// <param name="groupId"></param>
		/// <param name="questions"></param>
		/// <returns></returns>
		DataTable GetQuestionGroupAnswerGroup(string groupId, DataTable questions)
		{ return GetQuestionGroupAnswerGroup(groupId, "", questions); }

		/// <summary>
		/// Get question in group an have the same answer group id
		/// </summary>
		/// <param name="groupId"></param>
		/// <param name="answerGroupId"></param>
		/// <param name="questions"></param>
		/// <returns></returns>
		DataTable GetQuestionGroupAnswerGroup(string groupId, string answerGroupId, DataTable questions)
		{
			DataTable result = questions.Copy();
			int index = 0;
			int mappingIndexInSource = 0;
			int totalQuestion = result.Rows.Count;
			DataRow dr;
			while (index < totalQuestion)
			{
				dr = result.Rows[index];
				if (dr["GroupId"].ToString() == groupId)
				{
					if (answerGroupId.Length > 0)
					{
						if (dr["AnswerGroupId"].ToString() == answerGroupId)
						{
							questions.Rows.RemoveAt(mappingIndexInSource);
							index += 1;
						}
						else
						{
							result.Rows.RemoveAt(index);
							totalQuestion = result.Rows.Count;
							mappingIndexInSource += 1;
						}
					}
					else
					{
						questions.Rows.RemoveAt(mappingIndexInSource);
						index += 1;
					}
				}
				else
				{
					result.Rows.RemoveAt(index);
					totalQuestion = result.Rows.Count;
					mappingIndexInSource += 1;
				}
				//if ()
			}

			return result;
		}

		/// <summary>
		/// Get answers by question id
		/// </summary>
		/// <param name="questionId"></param>
		/// <returns></returns>
		DataTable GetAnswers(string questionId)
		{
			return _dataH.Load(_conn, "SELECT * FROM Answers WHERE QuestionId=@QuestionId", 0, 10,
					_dataH.CreateParam("QuestionId", SqlDbType.Char, questionId));
		}
		/// <summary>
		/// render normal question
		/// </summary>
		/// <param name="dr"></param>
		HtmlTable RenderQuestion(bool isReview, string prefix, DataRow dr)
		{ return RenderQuestion(isReview, prefix, true, dr); }
		HtmlTable RenderQuestion(bool isReview, string prefix, bool isRenderQuestionContent, DataRow question)
		{
			var table = new HtmlTable();
			table.ID = question["Id"].ToString();
			_logger.DebugFormat("Method: {0}; render question Id: {1}; Content: {2}", "RenderQuestion", question["Id"], question["Name"]);

			int renderAnswerMode = 1;
			if (question["RenderAnswerMode"] != DBNull.Value)
				renderAnswerMode = (int)question["RenderAnswerMode"];

			QuestionTypes type = QuestionTypes.ChoiseOne;
			if (question["QuestionType"] != DBNull.Value)
				type = (QuestionTypes)(int)question["QuestionType"];

			//load answer of question
			var answers = GetAnswers(question["Id"].ToString());
			//_dataH.Load(_conn, "SELECT * FROM Answers WHERE QuestionId=@QuestionId", 0, 10,
			//_dataH.CreateParam("QuestionId", SqlDbType.Char, dr["Id"].ToString()));

				if (renderAnswerMode == 1)
				{
					//question
					//answer 1 | answer 2 | answer 3
					#region //render on two line

					var row = new HtmlTableRow();
					var cell = new HtmlTableCell();
					if (isRenderQuestionContent)
					{
						//question content
						cell.Controls.Add(RenderQuestionControlView(question, prefix));
						//cell.InnerHtml = "<a name='" + question["Id"].ToString() + "'></a>"
						//  + (prefix.Length < 1 ? "" : "<span class='prefix'>" + prefix + ": </span>")
						//  + question["Name"].ToString();
						cell.ColSpan = answers.Rows.Count;
						row.Cells.Add(cell);
						table.Rows.Add(row);
					}
					//answers
					row = new HtmlTableRow();
					if (answers.Rows.Count < 2 && (bool)answers.Rows[0]["IsAllowComment"])
					{
						//if has one answer
						var answerRow = answers.Rows[0];
						if (answerRow["Name"].ToString() != question["Name"].ToString())
						{
							cell = new HtmlTableCell();
							cell.InnerText = answerRow["Name"].ToString();
							row.Cells.Add(cell);
						}

						cell = new HtmlTableCell();
						cell.Controls.Add(new TextBox() { ID = question["Id"].ToString() + "_" + answerRow["Id"].ToString() + "_Comment" });
						row.Cells.Add(cell);
					}
					else
					{
						foreach (DataRow item in answers.Rows)
						{
							cell = new HtmlTableCell();
							//cell.InnerHtml = item["Name"].ToString();
							cell.Controls.Add(GetAnswerControl(question["Id"].ToString() + "_" + item["Id"].ToString(), type, item["Name"].ToString(), question["Id"].ToString(), isReview ? HasCheckInCache(question["Id"].ToString(), item["Id"].ToString()) : false));
							row.Cells.Add(cell);
						}
					}

					//assign row to table
					table.Rows.Add(row);

					#endregion

					//add question to form
					//SurveyFormPanel.Controls.Add(table);
				}
				else if (renderAnswerMode == 2)
				{
					//question
					//answer 1
					//answer 2
					#region //render on two line

					var row = new HtmlTableRow();
					var cell = new HtmlTableCell();
					if (isRenderQuestionContent)
					{
						//question content
						cell.Controls.Add(RenderQuestionControlView(question, prefix));
						//cell.InnerHtml = "<a name='" + question["Id"].ToString() + "'></a>"
						//  + (prefix.Length < 1 ? "" : "<span class='prefix'>" + prefix + ": </span>")
						//  + question["Name"].ToString();
						cell.ColSpan = answers.Rows.Count;
						row.Cells.Add(cell);
						table.Rows.Add(row);
					}
					//answers
					if (answers.Rows.Count < 2 && (bool)answers.Rows[0]["IsAllowComment"])
					{
						//if has one answer
						var answerRow = answers.Rows[0];
						row = new HtmlTableRow();
						if (answerRow["Name"].ToString() != question["Name"].ToString())
						{
							cell = new HtmlTableCell();
							cell.InnerText = answerRow["Name"].ToString();
							row.Cells.Add(cell);
						}

						cell = new HtmlTableCell();
						cell.Controls.Add(new TextBox() { ID = question["Id"].ToString() + "_" + answerRow["Id"].ToString() + "_Comment" });
						row.Cells.Add(cell);
						table.Rows.Add(row);
					}
					else
					{
						foreach (DataRow item in answers.Rows)
						{
							row = new HtmlTableRow();
							cell = new HtmlTableCell();
							//cell.InnerHtml = item["Name"].ToString();
							var answerControl = GetAnswerControl(question["Id"].ToString() + "_" + item["Id"].ToString(), type, item["Name"].ToString(), question["Id"].ToString(), isReview ? HasCheckInCache(question["Id"].ToString(), item["Id"].ToString()) : false);
							if ((bool)item["IsAllowComment"])
								answerControl.ID += "_HasComment";
							cell.Controls.Add(answerControl);
							if ((bool)item["IsAllowComment"])
								cell.Controls.Add(new TextBox() { ID = question["Id"].ToString() + "_" + item["Id"].ToString() + "_Comment" });

							row.Cells.Add(cell);
							//assign row to table
							table.Rows.Add(row);
						}
					}

					#endregion

					//add question to form
					//SurveyFormPanel.Controls.Add(table);
					//
				}
				else
				{
					//question | answer 1 | answer 2 | answer 3
					#region //render on one line

					var row = new HtmlTableRow();
					var cell = new HtmlTableCell();
					if (isRenderQuestionContent)
					{
						cell.Controls.Add(RenderQuestionControlView(question, prefix));
						//question content
						//cell.InnerHtml = "<a name='" + question["Id"].ToString() + "'></a>"
						//  + (prefix.Length < 1 ? "" : "<span class='prefix'>" + prefix + ": </span>")
						//  + question["Name"].ToString();
						row.Cells.Add(cell);
					}
					//answers
					if (answers.Rows.Count < 2 && (bool)answers.Rows[0]["IsAllowComment"])
					{
						//if has one answer
						var answerRow = answers.Rows[0];
						row = new HtmlTableRow();
						if (answerRow["Name"].ToString() != question["Name"].ToString())
						{
							cell = new HtmlTableCell();
							cell.InnerText = answerRow["Name"].ToString();
							row.Cells.Add(cell);
						}

						cell = new HtmlTableCell();
						cell.Controls.Add(new TextBox() { ID = question["Id"].ToString() + "_" + answerRow["Id"].ToString() + "_Comment" });
						row.Cells.Add(cell);
						table.Rows.Add(row);
					}
					else
					{
						foreach (DataRow item in answers.Rows)
						{
							cell = new HtmlTableCell();
							//cell.InnerHtml = item["Name"].ToString();
							cell.Controls.Add(GetAnswerControl(question["Id"].ToString() + "_" + item["Id"].ToString(), type, item["Name"].ToString(), question["Id"].ToString(), isReview ? HasCheckInCache(question["Id"].ToString(), item["Id"].ToString()) : false));
							row.Cells.Add(cell);
						}
					}
					//assign row to table
					table.Rows.Add(row);

					#endregion

					//add question to form
					//SurveyFormPanel.Controls.Add(table);
				}

			return table;
		}

		Control RenderQuestionControlView(DataRow question, string prefix)
		{
			//"<a name='" + question["Id"].ToString() + "'></a>"
			//      + (prefix.Length < 1 ? "" : "<span class='prefix'>" + prefix + ": </span>")
			//      + question["Name"].ToString()
			HtmlGenericControl result = new HtmlGenericControl("div");
			
			HtmlGenericControl item = new HtmlGenericControl("a");
			item.Attributes.Add("Name", question["Id"].ToString());
			result.Controls.Add(item);
			if (prefix.Length > 0)
			{
				item = new HtmlGenericControl("span");
				item.Attributes.Add("class", "prefix");
				item.InnerHtml = prefix;
				result.Controls.Add(item);
			}

			if (_canEdit)
			{
				item = new HtmlGenericControl("a");
				item.Attributes.Add("href", "Details.aspx?Id=" + question["Id"].ToString());
				item.InnerHtml = question["Name"].ToString();
				result.Controls.Add(item);
			}
			else
			{
				item = new HtmlGenericControl("span");
				item.InnerHtml = question["Name"].ToString();
				result.Controls.Add(item);
			}

			return result;
		}

		#region generate question group

		HtmlTable RenderQuestionAnswerGroup(bool isReview, string prefix, DataRow group, DataRow answerGroup, DataTable questions)
		{
			return RenderQuestionAnswerGroup(isReview, prefix, group, answerGroup, questions, null);
		}
		HtmlTable RenderQuestionAnswerGroup(bool isReview, string prefix, DataRow group, DataRow answerGroup, DataTable questions, DataTable questionSave)
		{
			HtmlTable result = new HtmlTable();
			HtmlTableRow row;
			HtmlTableCell cell;

			DataTable answers = null;
			if (answerGroup == null)
			{ }
			else
				answers = GetAnswers(answerGroup["Id"].ToString());
			//_dataH.Load(_conn, "SELECT * FROM Answers WHERE QuestionId=@QuestionId", 0, 100,
			//        _dataH.CreateParam("QuestionId", SqlDbType.Char, answerGroup["Id"].ToString()));
			if (group["Name"].ToString() != answerGroup["Name"].ToString())
			{
				//generate answer group header
				row = new HtmlTableRow();
				cell = new HtmlTableCell();
				cell.ColSpan = answers.Rows.Count;
				//cell.Controls.Add(GetQuestionControlView())
				cell.InnerHtml = (prefix.Length < 1 ? "" : "<span class='prefix'>" + prefix + ": </span>")
					+ (_canEdit?"<a href='../Question/Details.aspx?Id=" + answerGroup["Id"].ToString() + "'>":"")
					+ answerGroup["Name"].ToString()
					+ (_canEdit?"</a>":"");
				row.Cells.Add(cell);
				result.Rows.Add(row);
			}

			//generate
			row = new HtmlTableRow();
			cell = new HtmlTableCell();
			cell.InnerHtml = "&nbsp;";
			row.Cells.Add(cell);
			//generate answer header
			foreach (DataRow item in answers.Rows)
			{
				cell = new HtmlTableCell();
				cell.InnerHtml = (_canEdit ? "<a href='../Answer/Details.aspx?Id=" + item["Id"].ToString() + "'>" : "")
					+ item["Name"].ToString()
					+ (_canEdit ? "</a>" : "");
				cell.Align = "center";
				row.Cells.Add(cell);
			}
			result.Rows.Add(row);
			//generate question
			foreach (DataRow item in questions.Rows)
			{
				if (questionSave != null)
					AddMappingQuestion(questionSave, item);

				result.Rows.Add(GenerateQuestionRow(isReview, true, item, answers));
			}

			return result;
		}

		/// <summary>
		/// Generate question to use answer group
		/// ----------- answer 1 | answer 2 | answer 3
		/// + question     x           x        x
		/// if isUseAnswerGroup do not render answer label 
		/// </summary>
		/// <param name="isUseAnswerGroup"></param>
		/// <param name="question"></param>
		/// <param name="answers"></param>
		/// <returns></returns>
		HtmlTableRow GenerateQuestionRow(bool isReview, bool isUseAnswerGroup, DataRow question, DataTable answers)
		{
			HtmlTableRow result = new HtmlTableRow();
			result.ID = question["Id"].ToString();
			HtmlTableCell cell;

			//generate qestion content
			cell = new HtmlTableCell();
			_logger.DebugFormat("Method: {0}; render question Id: {1}; Content: {2}", "GenerateQuestionRow", question["Id"], question["Name"]);
			//cell.InnerHtml = "<a name='" + question["Id"].ToString() + "'></a>" + question["Name"].ToString();
			cell.Controls.Add(RenderQuestionControlView(question, ""));
			result.Cells.Add(cell);

			//generate answer
			RadioButton rad;
			foreach (DataRow item in answers.Rows)
			{
				cell = new HtmlTableCell();
				rad = new RadioButton() { ID = question["Id"].ToString() + "_" + item["Id"].ToString(), Text = isUseAnswerGroup ? "" : item["Name"].ToString(), ToolTip = item["Name"].ToString(), GroupName = question["Id"].ToString() };
				rad.Checked = isReview ? HasCheckInCache(question["Id"].ToString(), item["Id"].ToString()) : false;
				cell.Controls.Add(rad);
				cell.Align = "center";
				result.Cells.Add(cell);
			}

			return result;
		}

		#endregion

		bool HasCheckInCache(string questionId, string answerId)
		{
			bool result = false;
			var answers = Answers;
			for (int i = 0; i < answers.Count; i++)
			{
				if (answers[i].QuestionId == questionId && answers[i].AnswerId == answerId)
				{
					result = true;
					break;
				}
			}

			return result;
		}

		Control GetAnswerControl(string id, QuestionTypes type, string answer, string group, bool isChecked)
		{
			Control result = null;
			if (type == QuestionTypes.ChoiseOne)
			{
				result = new RadioButton() { ID = id, Text = answer, GroupName = group, Checked = isChecked };
			}
			else
			{
				result = new CheckBox() { ID = id, Text = answer, Checked = isChecked };
			}

			var container = new HtmlGenericControl("span");
			container.Controls.Add(result);
			container.ID = "Span_"+id;
			if (_canEdit)
			{
				id = id.Replace("_HasComment", "");
				var item = new HtmlGenericControl("a");
				item.InnerText = " Edit";
				int index = id.LastIndexOf("_");
				string url = "../Answer/Details.aspx?Id=" + id.Substring(index + 1);
				index = id.IndexOf("_");
				url += "&QuestionId=" + id.Substring(0, index);
				item.Attributes.Add("href", url);
				container.Controls.Add(item);
			}
			//result.Controls.Add(item);

			//result = item;

			return container;
		}

		protected void SubmitButton_Click(object sender, EventArgs e)
		{
			List<Answer> answers = null;
			try
			{
				answers = CollectAnswers();
			}
			catch (Exception ex)
			{
				msg.Text = ex.Message;
#if DEBUG
				msg.Text = ex.ToString().Replace("\r\n", "<br/>");
#endif
			}
		}

		List<Answer> CollectAnswers()
		{
			List<Answer> result = new List<Answer>();
			DataRow dr;
			List<CheckBox> answers;
			Control container = null;
			Label commentInput;
			string questionId = "";

			_conn.Open();
			try
			{
				for (int i = 0; i < _questions.Rows.Count; i++)
				{
					#region travel all question

					dr = _questions.Rows[i];
					questionId = dr["Id"].ToString();
					container = PageHelper.FindControlRecursive(SurveyFormPanel, questionId);
					var answersSource = _dataH.Load("SELECT * FROM Answers WHERE QuestionId=@QuestionId", 0, 50,
						_dataH.CreateParam("QuestionId", SqlDbType.Char, questionId));

					if (answersSource.Rows.Count == 1 && (bool)answersSource.Rows[0]["IsAllowcomment"])
					{
						string itemId = answersSource.Rows[0]["Id"].ToString();
						//has one answer, and answer mark has comment
						//find comment control
						commentInput = PageHelper.FindControlRecursive(container, questionId + "_" + itemId + "_" + "_Comment") as Label;
						string comment = string.Empty;
						if (commentInput != null) comment = commentInput.Text.Trim();
						result.Add(new Answer() { QuestionId = dr["Id"].ToString(), AnswerId = itemId, Comment = comment });
					}
					else
					{
						answers = PageHelper.FindCheckBox(container, questionId);

						//answers = FindAllAnswer(dr["Id"].ToString());
						if (answers.Count < 1)
						{
							ClientScript.RegisterStartupScript(this.GetType(), "hash", "location.hash = '#" + dr["Id"].ToString() + "';", true);
							throw new Exception("Bạn chưa chọn câu trả lời cho câu hỏi: " + dr["Name"].ToString());
						}

						foreach (var item in answers)
						{
							if (item.ID.EndsWith("_HasComment"))
							{
								//find comment control
								commentInput = PageHelper.FindControlRecursive(container, item.ID + "_Comment") as Label;
								string comment = string.Empty;
								if (commentInput != null) comment = commentInput.Text.Trim();
								result.Add(new Answer() { QuestionId = dr["Id"].ToString(), AnswerId = item.ID.Replace(dr["Id"].ToString() + "_", "").Replace("_HasComment", ""), Comment = comment });
							}
							else
								result.Add(new Answer() { QuestionId = dr["Id"].ToString(), AnswerId = item.ID.Replace(dr["Id"].ToString() + "_", "") });
						}
					}
					#endregion
				}
			}
			finally
			{
				_conn.Close();
			}

			return result;
		}

		List<CheckBox> FindAllAnswer(string questionId)
		{
			List<CheckBox> result = new List<CheckBox>();
			//find container
			var container = PageHelper.FindControlRecursive(SurveyFormPanel, questionId);
			result = PageHelper.FindCheckBox(container, questionId);

			return result;
		}

		int CurrentQuestionIndex
		{
			get
			{
				int result = 1;
				if (ViewState["CurrentQuestionIndex"] != null)
					result = (int)ViewState["CurrentQuestionIndex"];
				return result;
			}
			set { ViewState["CurrentQuestionIndex"] = value; }
		}

		/// <summary>
		/// Save answer when display paging
		/// </summary>
		List<Answer> Answers
		{
			get
			{
				List<Answer> result = new List<Answer>();
				if (ViewState["Answers"] != null)
					result = (List<Answer>)ViewState["Answers"];
				return result;
			}
			set
			{
				ViewState["Answers"] = value;
			}
		}

		[Serializable]
		class Answer
		{
			public string QuestionId { get; set; }
			public string AnswerId { get; set; }
			public string Comment { get; set; }
		}

		protected void NextButton_Click(object sender, EventArgs e)
		{
			//collect current question(s) data
			List<Answer> answers = null;
			try
			{
				answers = CollectAnswers();

				var currentAnswers = Answers;
				for (int i = 0; i < answers.Count; i++)
				{
					currentAnswers.Add(answers[i]);
				}

				Answers = currentAnswers;

				//clrear survey form
				SurveyFormPanel.Controls.Clear();
				//increase question index
				CurrentQuestionIndex += 1;
				//render next question
				LoadData(_campaignId);
			}
			catch (Exception ex)
			{
				msg.Text = ex.Message;
#if DEBUG
				msg.Text = ex.ToString().Replace("\r\n", "<br/>");
#endif
			}
		}

		protected void SubmitAfterReviewButton_Click(object sender, EventArgs e)
		{

		}

		protected void SearchButton_Click(object sender, EventArgs e)
		{

		}

		#region helper working with caching
		DataTable AllQuestion
		{
			get
			{
				DataTable result = null;
				if (Cache["AllQuestion"] != null)
					result = (DataTable)Cache["AllQuestion"];

				return result;
			}
		}

		DataTable AllAnswer
		{
			get
			{
				DataTable result = null;
				if (Cache["AllAnswer"] != null)
					result = (DataTable)Cache["AllAnswer"];

				return result;
			}
		}

		DataTable AllGroup
		{
			get
			{
				DataTable result = null;
				if (Cache["AllGroup"] != null)
					result = (DataTable)Cache["AllGroup"];

				return result;
			}
		}

		void InitSystem(Guid campaignId)
		{
			int timeExpire = 10;
			if (Cache["CacheFlag"] == null)
			{
				Cache.Insert("CacheFlag", "CacheFlag", null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(timeExpire));
				
				_conn = _dataH.CreateConnection();
				try
				{
					_conn.Open();
					try
					{
						var allQuestion = _dataH.Load(_conn, "SELECT * FROM Questions WHERE CampaignId=@CampaignId", 0, 1000,
							_dataH.CreateParam("CampaignId", SqlDbType.Char, GlobalApplication.GetGuidS(campaignId)));

						var allAnswer = _dataH.Load(_conn, "SELECT * FROM Answers WHERE CampaignId=@CampaignId", 0, 1000,
							_dataH.CreateParam("CampaignId", SqlDbType.Char, GlobalApplication.GetGuidS(campaignId)));

						var allGroup = _dataH.Load(_conn, "SELECT * FROM Groups WHERE CampaignId=@CampaignId", 0, 1000,
							_dataH.CreateParam("CampaignId", SqlDbType.Char, GlobalApplication.GetGuidS(campaignId)));

						//save to cache
						Cache.Insert("AllQuestion", allQuestion, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(timeExpire));
						Cache.Insert("AllAnswer", allAnswer, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(timeExpire));
						Cache.Insert("AllGroup", allGroup, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(timeExpire));
					}
					finally
					{
						_conn.Close();
					}
				}
				catch
				{
				
				}
			}
		}

		DataTable GetQuestionInGroup(string groupId)
		{
			DataTable result = AllQuestion;

			int total = result.Rows.Count;
			int index = 0;
			while (index < total)
			{
				if (result.Rows[index]["GroupId"].ToString() != groupId)
				{
					result.Rows.RemoveAt(index);
					total = result.Rows.Count;
				}
				else
					index += 1;
			}

			return result;
		}
		#endregion
	}
}